package com.niiwoo.civet.trade.service.local.newRefund.dispatch;


import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.niiwoo.civet.account.dto.request.ReceivedRepaymentSuccessAccountingRequestDTO;
import com.niiwoo.civet.account.dto.response.AccountCompanyDTO;
import com.niiwoo.civet.account.enums.OrderTypeEnum;
import com.niiwoo.civet.account.service.AccountCompanyDubboService;
import com.niiwoo.civet.account.service.AccountDubboService;
import com.niiwoo.civet.account.service.trade.TransOrderDubboService;
import com.niiwoo.civet.base.constant.OrgConstant;
import com.niiwoo.civet.base.enums.OrderTradeSourceEnum;
import com.niiwoo.civet.base.enums.RefundTypeEnum;
import com.niiwoo.civet.trade.constant.DatePatternConstant;
import com.niiwoo.civet.trade.constant.MqConstant;
import com.niiwoo.civet.trade.dao.entity.*;
import com.niiwoo.civet.trade.dao.mapper.*;
import com.niiwoo.civet.trade.dto.newRefund.RefundCompensatoryDTO;
import com.niiwoo.civet.trade.dto.newRefund.RefundRepaymentDTO;
import com.niiwoo.civet.trade.dto.request.RefundWithholdRequestDTO;
import com.niiwoo.civet.trade.enums.RefundOrderAccountingStatusEnum;
import com.niiwoo.civet.trade.service.local.newRefund.refundDeal.RefundForGuaranteeService;
import com.niiwoo.civet.trade.service.local.newRefund.refundDeal.RefundForRepaymentService;
import com.niiwoo.civet.trade.service.local.refund.CommonLocalService;
import com.niiwoo.civet.trade.service.newRefund.RefundWithholdDubboService;
import com.niiwoo.civet.trade.utils.RepaymentUtil;
import com.niiwoo.tripod.base.utils.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.FastDateFormat;
import org.joda.time.DateTime;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;


/**
 * 还款辅助类
 * @author wangjun
 */
@Slf4j
@Service
public class RefundHelperLocalService
{
    @Autowired
    protected CommonLocalService commonLocalService;
    @Autowired
    protected ProjectBorrowerSummaryMapperExt summaryMapperExt;
    @Autowired
    protected RabbitTemplate rabbitTemplate;

    @Reference(version = "1.0.0")
    protected AccountDubboService accountDubboService;
    @Autowired
    protected WithholdLocalService withholdLocalService;
    @Reference(version = "1.0.0")
    RefundWithholdDubboService withholdDubboService;
    @Autowired
    protected ProjectInvestorPlanMapperExt projectInvestorPlanMapperExt;

    @Autowired
    protected RefundWithholdOrderMapperExt refundWithholdOrderMapperExt;

    @Autowired
    protected RefundOrderMapperExt refundOrderMapperExt;

    @Autowired
    protected RefundOrderDetailMapperExt refundOrderDetailMapperExt;

    @Reference(version = "1.0.0")
    protected TransOrderDubboService transOrderDubboService;
    @Reference(version = "1.0.0")
    protected AccountCompanyDubboService accountCompanyDubboService;

    @Autowired
    AdvanceConfigMapperExt advanceConfigMapperExt;

    @Autowired
    RefundForGuaranteeService refundForGuaranteeService;
    @Autowired
    RefundForRepaymentService refundForRepaymentService;
    @Autowired
    ProjectBorrowerPlanNewMapperExt borrowerPlanNewMapperExt;
    @Autowired
    ProjectMapperExt projectMapperExt;

    /**
     * 扫描需还款用户
     * @return
     */
    protected List<String> repayScan(String date)
    {
        return borrowerPlanNewMapperExt.listRepayUserIds(date);
    }

    /**
     * 扫描需代扣标的
     * @return
     */
    protected List<ProjectBorrowerSummary> withholdScan(String date)
    {
        return summaryMapperExt.listWithhold(date);
    }

    /**
     * 扫描未垫付
     * @param date
     * @return
     */
    protected List<Map<String,Object>> historyCompensatoryScanByOverdueDays(Date date)
    {
        return projectInvestorPlanMapperExt.historyCompensatoryScanByOverdueDays(date);
    }

    /**
     * 部分划扣计划任务触发，扫描当日应还款用户入队
     */
    public void partialRefund()
    {
        log.info("RefundHelperLocalService -> partialRefund start");

        Date currentDate = commonLocalService.getCurrentDate();
        List<String> list = this.repayScan(commonLocalService.day2String(currentDate));
        if (!CollectionUtils.isEmpty(list))
        {
            log.info("RefundHelperLocalService -> partialRefund begining:list.size={}", list.size());
            RefundRepaymentDTO repaymentDTO = new RefundRepaymentDTO();
            list.forEach(userId ->
            {
                try
                {
                    repaymentDTO.setUserId(userId);
                    repaymentDTO.setCurrentDate(currentDate);
                    log.info("RefundHelperLocalService -> partialRefund msg send:userId={}",userId);
                    rabbitTemplate.convertAndSend(MqConstant.REFUNDNEW_EXCHANGE, MqConstant.REFUNDNEW_PARTIAL_ROUTE, repaymentDTO);
                }
                catch (Exception e)
                {
                    log.error("RefundHelperLocalService ->partialRefund error msg send:userId={}",userId,e);
                }
            });
        }

        log.info("RefundHelperLocalService -> partialRefund end");
    }


    /**
     * 部分划扣前置处理，用于计划任务出队
     * @param repaymentDTO
     */
    public void partialRefund(RefundRepaymentDTO repaymentDTO)
    {
        log.info("RefundHelperLocalService ->partialRefund receive:userId={},repaymentDTO={}",repaymentDTO.getUserId(),repaymentDTO);
        refundForRepaymentService.refundForRepaymentForJob(
                repaymentDTO.getUserId(),
                OrderTradeSourceEnum.BALANCE_PARTIAL_JOB,
                repaymentDTO.getCurrentDate());
    }


    /**
     * 全额划扣计划任务触发，扫描当日应还款用户入队
     */
    public void fullRefund()
    {
        log.info("RefundHelperLocalService ->fullRefund start");

        Date currentDate = commonLocalService.getCurrentDate();
        List<String> list = this.repayScan(commonLocalService.day2String(currentDate));
        if (!CollectionUtils.isEmpty(list))
        {
            log.info("FRefundHelperLocalService ->fullRefund begining,list.size={}", list.size());
            RefundRepaymentDTO repaymentDTO = new RefundRepaymentDTO();
            list.forEach(userId ->
            {
                try
                {
                    repaymentDTO.setUserId(userId);
                    repaymentDTO.setCurrentDate(currentDate);
                    log.info("RefundHelperLocalService ->fullRefund msg send:userId={}",userId);
                    rabbitTemplate.convertAndSend(MqConstant.REFUNDNEW_EXCHANGE, MqConstant.REFUNDNEW_FULL_ROUTE, repaymentDTO);
                }
                catch (Exception e)
                {
                    log.error("RefundHelperLocalService ->fullRefund error msg send:userId={}",userId,e);
                }
            });
        }

        log.info("RefundHelperLocalService ->fullRefund end");
    }


    /**
     * 全额划扣前置处理，用于计划任务出队
     * @param repaymentDTO
     */
    public void fullRefund(RefundRepaymentDTO repaymentDTO) {
        log.info("RefundHelperLocalService ->fullRefund receive:userId={},repaymentDTO={}",repaymentDTO.getUserId(),repaymentDTO);
        refundForRepaymentService.refundForRepaymentForJob(
                repaymentDTO.getUserId(),
                OrderTradeSourceEnum.BALANCE_FULL_JOB,
                repaymentDTO.getCurrentDate());
    }

    /**
     * 垫付计划任务触发，扫描当日应还款用户入队
     */
    public void compensatoryRefund()
    {
        log.info("RefundHelperLocalService ->compensatoryRefund start");

        Date currentDate = commonLocalService.getCurrentDate();

        //查询所有需要垫付的标的
        CompletableFuture.runAsync(() ->
        {
            AdvanceConfig advanceConfig = advanceConfigMapperExt.selectByPrimaryKey(OrgConstant.NIIWOO_ORG_ID);
            if(null == advanceConfig || !Byte.valueOf("1").equals(advanceConfig.getNeedJob()))
            {
                log.info("RefundHelperLocalService ->compensatoryRefund history,advanceConfig null or not neddjob: advanceConfig={}",advanceConfig);
                return;
            }
            //垫付标的收集
            log.info("查询待垫付标的start，时间:{}",DateUtils.getCurrDatetime());
            List<Map<String,Object>> list = this.historyCompensatoryScanByOverdueDays(currentDate);
            log.info("查询待垫付标的end，时间:{},list.size={}",DateUtils.getCurrDatetime(),list.size());

            Set<String> setGuarantees = new HashSet<>();//收集担保公司user_id
            //guarantee_company_org_id指向担保公司user_id,org_id是推标机构ID
            list.forEach( p -> setGuarantees.add(p.get("guarantee_company_org_id").toString()));
            if (setGuarantees.size() == 0){
                log.info("数据为空,无需垫付,currentDate={}",currentDate);
                return;
            }
            log.info("收集担保公司mapGuarantees={}", JSON.toJSONString(setGuarantees));
            Map<String,AccountCompanyDTO> userMaps = new HashMap<>();
            for (String guaranteeCompanyOrgId : setGuarantees) {
                try {
                    AccountCompanyDTO accountCompanyDTO = accountCompanyDubboService.getGuaranteeOrgByOrgId(guaranteeCompanyOrgId);
                    userMaps.put(guaranteeCompanyOrgId, accountCompanyDTO);
                }catch (Exception e){
                    log.error("据用户userId查询账户信息异常userId={}",guaranteeCompanyOrgId,e);
                }
            }
            if (!CollectionUtils.isEmpty(list))
            {
                log.info("RefundHelperLocalService ->compensatoryRefund begining,list.size={}", list.size());
                RefundCompensatoryDTO compensatoryDTO = new RefundCompensatoryDTO();
                for (Map<String, Object> map : list) {
                    try {
                        //担保公司user_id
                        String guaranteeUserId = map.get("guarantee_company_org_id").toString();
                        Date compareDate = new DateTime(currentDate).minusDays(Integer.parseInt(map.get("advance_overdue_days").toString())).toDate();
                        log.info("RefundHelperLocalService->compensatoryRefund.map={},compareDate={}", JSON.toJSONString(map),compareDate);
                        compensatoryDTO.setProjectId(Long.parseLong(map.get("project_id").toString()));
                        compensatoryDTO.setCurrentDate(currentDate);
                        compensatoryDTO.setCompareDate(compareDate);
                        compensatoryDTO.setSourceUserId(guaranteeUserId);
                        compensatoryDTO.setSourceAccountId(userMaps.get(guaranteeUserId).getAccountId());
                        compensatoryDTO.setSourcePlatformUserNo(userMaps.get(guaranteeUserId).getAccountNo());
                        log.info("RefundHelperLocalService ->compensatoryRefund history msg send:projectId={},compensatoryDTO={}", compensatoryDTO.getProjectId(), compensatoryDTO);
                        rabbitTemplate.convertAndSend(MqConstant.REFUNDNEW_EXCHANGE, MqConstant.REFUNDNEW_COMPENSATORY_ROUTE, compensatoryDTO);
                    } catch (Exception e) {
                        log.error("RefundHelperLocalService ->compensatoryRefund history error,msg send:projectId={}", compensatoryDTO.getProjectId(), e);
                    }
                }
            }
        });
        log.info("RefundHelperLocalService ->compensatoryRefund end");

    }


    /**
     * 垫付还款前置处理，用于计划任务出队
     * @param compensatoryDTO
     */
    public void compensatoryRefund(RefundCompensatoryDTO compensatoryDTO)
    {
        try
        {
            //执行垫付
            log.info("RefundHelperLocalService->compensatoryRefund request:projectId={},compensatoryDTO={}",compensatoryDTO.getProjectId(),compensatoryDTO);
            RefundOrder refundOrder = refundForGuaranteeService.refund(
                    compensatoryDTO.getProjectId(),
                    OrderTradeSourceEnum.GUARANTEE_JOB,
                    compensatoryDTO.getCurrentDate(),
                    compensatoryDTO.getCompareDate(),
                    compensatoryDTO.getSourceUserId(),
                    compensatoryDTO.getSourcePlatformUserNo(),
                    compensatoryDTO.getSourceAccountId());
            log.info("RefundHelperLocalService->compensatoryRefund response:projectId={},refundOrder={}",compensatoryDTO.getProjectId(),refundOrder);
        }
        catch (Exception e)
        {
            log.error("RefundHelperLocalService->compensatoryRefund error:projectId={}",compensatoryDTO.getProjectId(),e);
        }
    }

    /**
     * 代扣计划任务触发，扫描当日应还款用户入队
     */
    public void withhold()
    {
        log.info("RefundHelperLocalService ->withhold start");

        //16点代扣更范围更大(第一次代扣)，20点代扣范围更小（第二次代扣），默认为16点代扣
        boolean isFirstJobWithhold = true;//是否是当天第一次代扣JOB,默认true
        if (DateTime.now().getHourOfDay() == 20){//当前时间为20点才做出拴选，踢除逾期较长的标的
            isFirstJobWithhold = false;
        }
        Date currentDate = commonLocalService.getCurrentDate();
        List<ProjectBorrowerSummary> list = this.withholdScan(commonLocalService.day2String(currentDate));
        if (!CollectionUtils.isEmpty(list))
        {
            log.info("RefundHelperLocalService ->withhold begining,list.size={}", list.size());
            final AtomicInteger counter = new AtomicInteger();
            RefundRepaymentDTO repaymentDTO = new RefundRepaymentDTO();
            for (ProjectBorrowerSummary summary : list) {
            /*
             * 还款日当天标的执行两次代扣，逾期1-15天、25天、31天、40天、50天、60天、90天的标的
             * 也是每天执行两次代扣下午4点跟晚上8点，逾期90天以上的标的就不再执行代扣了
             */
                try {
                    long overdueDays = DateUtils.daysBetween(summary.getRefundDate(), currentDate);
                    if ( (isFirstJobWithhold && (overdueDays <= 15 || overdueDays == 25 || overdueDays == 31 || overdueDays == 50))
                            || (!isFirstJobWithhold && overdueDays <= 5 )) {
                        repaymentDTO.setProjectId(summary.getProjectId());
                        repaymentDTO.setCurrentDate(currentDate);
                        log.info("RefundHelperLocalService ->withhold msg send:projectId={}", summary.getProjectId());
                        rabbitTemplate.convertAndSend(MqConstant.REFUNDNEW_EXCHANGE, MqConstant.REFUNDNEW_WITHHOLD_ROUTE, repaymentDTO);
                        counter.getAndIncrement();
                    }
                } catch (Exception e) {
                    log.error("RefundHelperLocalService ->withhold error,msg send:projectId={}", summary.getProjectId(), e);
                }
            }
            log.info("RefundHelperLocalService ->withhold send,counter={}", counter.get());
        }

        log.info("RefundHelperLocalService ->withhold end");
    }


    /**
     * 代扣处理，用于计划任务出队
     * @param repaymentDTO
     */
    public void withhold(RefundRepaymentDTO repaymentDTO)
    {
        log.info("RefundHelperLocalService ->withhold receive:projectId={},repaymentDTO={}",repaymentDTO.getProjectId(),repaymentDTO);
        ProjectBorrowerSummary summary = summaryMapperExt.select(repaymentDTO.getProjectId(),commonLocalService.day2String(repaymentDTO.getCurrentDate()));
        if (summary == null) return;
        //调用代扣接口
        RefundWithholdRequestDTO requestDTO = new RefundWithholdRequestDTO();
        requestDTO.setProjectId(repaymentDTO.getProjectId());
        requestDTO.setRefundType(RefundTypeEnum.IMMEDIATELY);
        requestDTO.setTradeSource(RefundWithholdRequestDTO.WithHoldTradeSourceEnum.JOB);
        requestDTO.setOptType(RefundWithholdRequestDTO.WithHoldOptTypeEnum.NORMAL);
        try
        {
            log.info("RefundHelperLocalService ->withhold request:projectId={},requestDTO={}",repaymentDTO.getProjectId(),requestDTO);
            withholdDubboService.withhold(requestDTO);
        }
        catch (Exception e)
        {
            log.error("RefundHelperLocalService ->withhold error:projectId={}",repaymentDTO.getProjectId(),e);
        }
    }

    public static final String ONLINE_DATE = "2019-04-01";

    @Autowired
    private ProjectBorrowerSummaryOverdue50DayMapperExt projectBorrowerSummaryOverdue50DayMapperExt;

    private List<ProjectBorrowerSummaryOverdue50Day> withholdForOverdue50DayScan(){
        Integer daysOnline = 0;
        try {
            daysOnline = RepaymentUtil.getOverdueDay(FastDateFormat.getInstance(DatePatternConstant.YYYY_MM_DD).parse(ONLINE_DATE), new Date()) ;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        log.info("RefundHelperLocalService ->withholdForOverdue50DayScan,daysOnline={}", daysOnline);
        Integer withholdDay = daysOnline % 3 + 1;
        return projectBorrowerSummaryOverdue50DayMapperExt.listWithhold(withholdDay);
    }

    /**
     * 逾期50天代扣处理代扣计划任务触发，扫描当日应还款用户入队
     */
    public void withholdForOverdue50Day() {
        log.info("RefundHelperLocalService ->withholdForOverdue50Day start");

        Date currentDate = commonLocalService.getCurrentDate();
        List<ProjectBorrowerSummaryOverdue50Day> list = this.withholdForOverdue50DayScan();
        if (!CollectionUtils.isEmpty(list)) {
            log.info("RefundHelperLocalService ->withholdForOverdue50Day beginning,list.size={}", list.size());
            final AtomicInteger counter = new AtomicInteger();
            RefundRepaymentDTO repaymentDTO = new RefundRepaymentDTO();
            for (ProjectBorrowerSummaryOverdue50Day summary : list) {
                try {
                    repaymentDTO.setProjectId(summary.getProjectId());
                    repaymentDTO.setCurrentDate(currentDate);
                    log.info("RefundHelperLocalService ->withholdForOverdue50Day msg send:projectId={}", summary.getProjectId());
                    rabbitTemplate.convertAndSend(MqConstant.WITHHOLD_APPLY_EXCHANGE, MqConstant.WITHHOLD_OVERDUE_50_DAY_ROUTING, repaymentDTO);
                    counter.getAndIncrement();
                } catch (Exception e) {
                    log.error("RefundHelperLocalService ->withholdForOverdue50Day error,msg send:projectId={}", summary.getProjectId(), e);
                }
            }
            log.info("RefundHelperLocalService ->withholdForOverdue50Day send,counter={}", counter.get());
        }

        log.info("RefundHelperLocalService ->withholdForOverdue50Day end");
    }

    /**
     * 逾期50天代扣处理，用于计划任务出队
     *
     * @param repaymentDTO
     */
    public void withholdForOverdue50Day(RefundRepaymentDTO repaymentDTO) {
        log.info("RefundHelperLocalService ->withholdForOverdue50Day receive:projectId={},repaymentDTO={}", repaymentDTO.getProjectId(), repaymentDTO);
        ProjectBorrowerSummary summary = summaryMapperExt.select(repaymentDTO.getProjectId(), commonLocalService.day2String(repaymentDTO.getCurrentDate()));
        if (summary == null) return;
        //调用代扣接口
        RefundWithholdRequestDTO requestDTO = new RefundWithholdRequestDTO();
        requestDTO.setProjectId(repaymentDTO.getProjectId());
        requestDTO.setRefundType(RefundTypeEnum.IMMEDIATELY);
        requestDTO.setAmount(new BigDecimal(100)); //只扣100
        requestDTO.setTradeSource(RefundWithholdRequestDTO.WithHoldTradeSourceEnum.OVERDUE_50_DAY);
        requestDTO.setOptType(RefundWithholdRequestDTO.WithHoldOptTypeEnum.NORMAL);
        try {
            log.info("RefundHelperLocalService ->withholdForOverdue50Day request:projectId={},requestDTO={}", repaymentDTO.getProjectId(), requestDTO);
            withholdDubboService.withhold(requestDTO);
        } catch (Exception e) {
            log.error("RefundHelperLocalService ->withholdForOverdue50Day error:projectId={}", repaymentDTO.getProjectId(), e);
        }
    }

    /**
     * 代扣补单计划任务触发
     */
    public void withholdSupplement()
    {
        log.info("RefundHelperLocalService ->withholdSupplement start");

        //代扣充值补单
        Optional.ofNullable(refundWithholdOrderMapperExt.listProcessing()).ifPresent(withholdOrders ->
        {
            withholdOrders.forEach(withholdOrder ->
            {
                withholdLocalService.withholdSupplement(withholdOrder);
            });
        });

        log.info("RefundHelperLocalService ->withholdSupplement end");
    }


    /**
     * 记账补单任务处理
     */
    public void accDetailSupplement()
    {
        log.info("RefundHelperLocalService ->accDetailSupplement start");
        //明细
        Optional.ofNullable(refundOrderDetailMapperExt.listForAccouting()).ifPresent(refundOrderDetails  ->
        {
            refundOrderDetails.forEach(refundOrderDetail ->
            {
                try
                {
                    log.info("RefundWithholdLocalService -> accDetailSupplement request:orderId={}",refundOrderDetail.getId(),refundOrderDetail);
                    //调用账户中心记账记账服务
                    ReceivedRepaymentSuccessAccountingRequestDTO requestDTO = new ReceivedRepaymentSuccessAccountingRequestDTO();
                    requestDTO.setOrderId(refundOrderDetail.getId());
                    requestDTO.setDetailRequestNo(refundOrderDetail.getBatchNo());
                    requestDTO.setOrderType(OrderTypeEnum.REPAYMENT);
                    transOrderDubboService.receivedRepaymentSuccessAccounting(requestDTO);
                    //更新记账状态
                    refundOrderDetail.setAccountingStatus(RefundOrderAccountingStatusEnum.SUCCESS.getValue());
                    refundOrderDetail.setUpdateTime(new Date());
                    refundOrderDetailMapperExt.updateByPrimaryKeySelective(refundOrderDetail);
                }
                catch (Exception e)
                {
                    log.error("RefundWithholdLocalService -> accDetailSupplement error:orderId={},", refundOrderDetail.getId(),e);
                }
            });
        });
        log.info("RefundHelperLocalService ->accDetailSupplement end");
    }

    /**
     * 记账补单任务处理
     */
    public void accountingSupplement()
    {
        log.info("RefundHelperLocalService ->accountingSupplement start");
        //订单
        Optional.ofNullable(refundOrderMapperExt.listForAccouting()).ifPresent(refundOrders  ->
        {
            refundOrders.forEach(refundOrder ->
            {
                try
                {
                    log.info("RefundWithholdLocalService -> accountingSupplement request:orderId={}",refundOrder.getId(),refundOrder);
                    //调用账户中心记账记账服务
                    transOrderDubboService.repaymentSuccessAccounting(refundOrder.getFreezeRequestNo());
                    //更新记账状态
                    refundOrder.setAccountingStatus(RefundOrderAccountingStatusEnum.SUCCESS.getValue());
                    refundOrder.setProcessStatus(Byte.valueOf("2")); // 帐户处理完成之前标记还款订单结束
                    Date updateTime = new Date();
                    refundOrder.setOverTime(updateTime); // 全部操作结束时间
                    refundOrder.setUpdateTime(updateTime);
                    refundOrderMapperExt.updateByPrimaryKeySelective(refundOrder);
                }
                catch (Exception e)
                {
                    log.error("RefundWithholdLocalService -> accountingSupplement error:orderId={},", refundOrder.getId(),e);
                }
            });
        });
        log.info("RefundHelperLocalService ->accountingSupplement end");
    }

    public void testCompensatoryRefund(String projectIds)
    {
        log.info("RefundWithholdLocalService -> testCompensatoryRefund:projectIds={}",projectIds);
        String[] projectIdArr = projectIds.split(",");
        for (String projectIdS : projectIdArr)
        {
            RefundCompensatoryDTO compensatoryDTO = new RefundCompensatoryDTO();
            Long projectId = Long.parseLong(projectIdS);
            compensatoryDTO.setProjectId(projectId);
            Project project = projectMapperExt.selectByPrimaryKey(projectId);
            Assert.notNull(project,"project must not be null");
            AccountCompanyDTO accountCompanyDTO = accountCompanyDubboService.getGuaranteeOrgByOrgId(project.getGuaranteeCompanyOrgId());
            Assert.notNull(accountCompanyDTO,"accountCompanyDTO must not be null");
            compensatoryDTO.setSourceAccountId(accountCompanyDTO.getAccountId());
            compensatoryDTO.setSourcePlatformUserNo(accountCompanyDTO.getAccountNo());
            compensatoryDTO.setSourceUserId(accountCompanyDTO.getUserId());
            Date currentDate = commonLocalService.getCurrentDate();
            Date compareDate = new DateTime(currentDate).minusDays(project.getAdvanceOverdueDays()).toDate();
            compensatoryDTO.setCurrentDate(currentDate);
            compensatoryDTO.setCompareDate(compareDate);
            this.compensatoryRefund(compensatoryDTO);
        }

    }

    public void testWithhold(String projectIds )
    {
        log.info("RefundWithholdLocalService -> testWithhold:projectIds={}",projectIds);
        String[] projectIdArr = projectIds.split(",");
        for (String projectIdS : projectIdArr)
        {
            Long projectId = Long.parseLong(projectIdS);
            RefundRepaymentDTO repaymentDTO = new RefundRepaymentDTO();
            repaymentDTO.setProjectId(projectId);
            repaymentDTO.setCurrentDate(commonLocalService.getCurrentDate());
            this.withhold(repaymentDTO);
        }
    }

    public void testRefund(String isFull,String projectIds)
    {
        log.info("RefundWithholdLocalService -> testRefund:isFull={},projectIds={}",isFull,projectIds);
        String[] projectIdArr = projectIds.split(",");
        for (String projectIdS : projectIdArr)
        {
            Long projectId = Long.parseLong(projectIdS);
            RefundRepaymentDTO repaymentDTO = new RefundRepaymentDTO();
            repaymentDTO.setCurrentDate(commonLocalService.getCurrentDate());
            repaymentDTO.setProjectId(projectId);
            try
            {
                //执行还款
                log.info("RefundHelperLocalService->testRefund request:projectId={},repaymentDTO={}",projectId,repaymentDTO);
                RefundOrder refundOrder =refundForRepaymentService.refundForRepaymentForJob(
                        projectId,
                        isFull.equals("1") ? OrderTradeSourceEnum.BALANCE_FULL_JOB : OrderTradeSourceEnum.BALANCE_PARTIAL_JOB,
                        repaymentDTO.getCurrentDate());
                log.info("RefundHelperLocalService->testRefund response:projectId={},refundOrder={}",projectId,refundOrder);
            }
            catch (Exception e)
            {
                log.error("RefundHelperLocalService ->testRefund error:projectId={}",projectId,e);
            }
        }
    }
}